package edu.xmut.yuepai.common.utils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class IpUtils {

    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST_IP = "127.0.0.1";
    // 客户端与服务器同为一台机器，获取的 ip 有时候是 ipv6 格式
    private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    private static final String SEPARATOR = ",";

    private static Searcher searcher;


    static {
        try {
            InputStream inputStream = new ClassPathResource("/ipdb/ip2region.xdb").getInputStream();
            byte[] bytes = FileCopyUtils.copyToByteArray(inputStream);
            searcher = Searcher.newWithBuffer(bytes);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * 判断是否为合法 IP
     *
     * @return
     */
    public boolean checkIp(String ipAddress) {
        String ip = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        Pattern pattern = Pattern.compile(ip);
        Matcher matcher = pattern.matcher(ipAddress);
        return matcher.matches();
    }


    /**
     * 获取 ip 所属地址
     *
     * @param ip ip
     * @return 返回ip所属的地区字符串，如果ip不合法或查询失败则返回空字符串
     */
    public String getIpRegion(String ip) {
        try {
            String searchIpInfo = getIpInfo(ip);
            // 将查询结果按'|'分割
            String[] splitIpInfo = searchIpInfo.split("\\|");
            // 如果分割结果不为空
            if (splitIpInfo.length > 0) {
                // 如果国家信息为"中国"
                if ("中国".equals(splitIpInfo[0])) {
                    // 国内属地返回省份
                    String province = splitIpInfo[2];
                    return province.replace("省", "");
                } else if ("0".equals(splitIpInfo[0])) {
                    // 如果国家信息为"0"且ISP为"内网IP"
                    if ("内网IP".equals(splitIpInfo[4])) {
                        // 内网 IP
                        return splitIpInfo[4];
                    } else {
                        return "";
                    }
                } else {
                    // 国外属地返回国家
                    return splitIpInfo[0];
                }
            } else {
                return "";
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getIpInfo(String ip) throws Exception {
        // 验证ip地址是否合法
        boolean isIp = checkIp(ip);
        // 如果ip地址合法
        if (isIp) {
            // 查询ip地址信息 = searchIpInfo 的数据格式： 国家|区域|省份|城市|ISP
            String searchIpInfo = searcher.search(ip);
            log.info("ip完整数据格式：{}", searchIpInfo);
            return searchIpInfo;
        } else {
            // 如果ip地址不合法，抛出IllegalArgumentException异常
            throw new IllegalArgumentException("非法的IP地址");
        }
    }

    /**
     * 根据 HttpServletRequest 获取 IP
     */
    public static String getIpAddress(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (LOCALHOST_IP.equalsIgnoreCase(ip) || LOCALHOST_IPV6.equalsIgnoreCase(ip)) {
                // 根据网卡取本机配置的 IP
                InetAddress iNet = null;
                try {
                    iNet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (iNet != null) {
                    ip = iNet.getHostAddress();
                }
            }
        }
        // 对于通过多个代理的情况，分割出第一个 IP
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(SEPARATOR) > 0) {
                ip = ip.substring(0, ip.indexOf(SEPARATOR));
            }
        }
        return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IP : ip;
    }


}
